package com.xiaoq.order.repository.impl;

import com.mongodb.WriteConcern;
import com.xiaoq.coms.util.ConstantUtil;
import com.xiaoq.order.entity.*;
import com.xiaoq.order.repository.IShopOrderRepository;
import com.xiaoq.order.vo.OrderQueryVo;
import com.xiaoq.order.vo.OrderTourPipeQueryVo;
import com.xiaoq.vo.PagingVo;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.mongodb.morphia.Datastore;
import org.mongodb.morphia.aggregation.Accumulator;
import org.mongodb.morphia.aggregation.AggregationPipeline;
import org.mongodb.morphia.query.Query;
import org.mongodb.morphia.query.Sort;
import org.mongodb.morphia.query.UpdateOperations;
import org.mongodb.morphia.query.UpdateResults;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import static org.mongodb.morphia.aggregation.Group.*;

/**
 * Created by chenjh on 2017/11/7.
 */
@Repository
public class ShopOrderRepositoryImpl implements IShopOrderRepository{

    private static final Logger LOGGER = LoggerFactory.getLogger(ShopOrderRepositoryImpl.class);

    @Autowired
    private Datastore datastore;

    @Override
    public void save(ShopOrderEntity shopOrderEntity) {
        if(shopOrderEntity != null){
            datastore.save(shopOrderEntity);
        }
    }

    @Override
    public ShopOrderEntity getShopOrder(String shopOrderId, String userId) {
        if(StringUtils.isAnyBlank(shopOrderId, userId)){
            return null;
        }

        Query<ShopOrderEntity> shopOrderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopOrderId", shopOrderId)
                .filter("userId", userId);
        return shopOrderEntityQuery.get();
    }

    @Override
    public ShopOrderEntity getShopOrder(String orderId) {
        if(StringUtils.isBlank(orderId)){
            return null;
        }

        Query<ShopOrderEntity> shopOrderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopOrderId", orderId);
        return shopOrderEntityQuery.get();
    }

    @Override
    public boolean cancelShopOrder(String shopOrderId, String userId) {
        Query<ShopOrderEntity> shopOrderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopOrderId", shopOrderId)
                .filter("userId", userId);
        long currentMillis = System.currentTimeMillis();
        UpdateOperations<ShopOrderEntity> ops = datastore.createUpdateOperations(ShopOrderEntity.class)
                .set("orderState", OrderState.CANCELED.value())
                .set("payState" , PayState.NOPAYMENT.value())
                .set("canceledTime", currentMillis)
                .set("updatedAt",currentMillis);

        UpdateResults updateResults = datastore.update(shopOrderEntityQuery, ops);
        return true;
    }

    @Override
    public List<ShopOrderEntity> getUserAllOrder(ShopOrderEntity shopOrderEntity) {
        if(shopOrderEntity==null || StringUtils.isBlank(shopOrderEntity.getUserId())){
            return new ArrayList<>();
        }
        Query<ShopOrderEntity> shopOrderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("userId", shopOrderEntity.getUserId());
        if(shopOrderEntity.getPayState() != null){
            shopOrderEntityQuery.filter("payState", shopOrderEntity.getPayState().intValue());
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getUserDeleteFlag())){
            shopOrderEntityQuery.filter("userDeleteFlag", shopOrderEntity.getUserDeleteFlag());
        }
        if(shopOrderEntity.getOrderState() != null){
            shopOrderEntityQuery.filter("orderState", shopOrderEntity.getOrderState().intValue());
        }
        if(shopOrderEntity.getOrderType() != null){
            shopOrderEntityQuery.filter("orderType", shopOrderEntity.getOrderType().intValue());
        }
        shopOrderEntityQuery.order("-updatedAt"); // 倒序排序
        return shopOrderEntityQuery.asList();
    }

    @Override
    public List<ShopOrderEntity> getInterpreterAllOrder(String interpreterId) {
        if(StringUtils.isBlank(interpreterId)){
            return new ArrayList<>();
        }
        Query<ShopOrderEntity> shopOrderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("interpreterId", interpreterId)
                .order("- createTime");
        return shopOrderEntityQuery.asList();
    }

    @Override
    public boolean updateByOrderId(ShopOrderEntity shopOrderEntity) {
        if(shopOrderEntity == null || StringUtils.isBlank(shopOrderEntity.getShopOrderId())){
            return false;
        }
        Query<ShopOrderEntity> shopOrderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopOrderId", shopOrderEntity.getShopOrderId());

        UpdateOperations<ShopOrderEntity> ops = datastore.createUpdateOperations(ShopOrderEntity.class);

        if(StringUtils.isNotBlank(shopOrderEntity.getCellphoneNumber())){
            ops.set("cellphoneNumber", shopOrderEntity.getCellphoneNumber());
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getUserRealName())){
            ops.set("userRealName", shopOrderEntity.getUserRealName());
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getShopName())){
            ops.set("shopName", shopOrderEntity.getShopName());
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getInterpreterId())){
            ops.set("interpreterId", shopOrderEntity.getInterpreterId());
        }
        if(shopOrderEntity.getPaidTime() != null){
            ops.set("paidTime", shopOrderEntity.getPaidTime());
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getCellphoneNumber())){
            ops.set("cellphoneNumber", shopOrderEntity.getCellphoneNumber());
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getNote())){
            ops.set("note", shopOrderEntity.getNote());
        }
        if(shopOrderEntity.getReceivedTime() != null){
            ops.set("receivedTime", shopOrderEntity.getReceivedTime());
        }
        if(shopOrderEntity.getDeliveriedTime() != null){
            ops.set("deliveriedTime", shopOrderEntity.getDeliveriedTime());
        }
        if(shopOrderEntity.getReviewedTime() != null){
            ops.set("reviewedTime", shopOrderEntity.getReviewedTime());
        }
        if(shopOrderEntity.getCompletedTime() != null){
            ops.set("completedTime", shopOrderEntity.getCompletedTime());
        }
        if(shopOrderEntity.getCanceledTime() != null){
            ops.set("canceledTime", shopOrderEntity.getCanceledTime());
        }
        if(shopOrderEntity.getClosedTime() != null){
            ops.set("closedTime", shopOrderEntity.getClosedTime());
        }
        if(shopOrderEntity.getUpdatedAt() != null){
            ops.set("updatedAt", shopOrderEntity.getUpdatedAt());
        }
        if(shopOrderEntity.getOrderState() != null){
            ops.set("orderState", shopOrderEntity.getOrderState());
        }
        if(shopOrderEntity.getPayState() != null){
            ops.set("payState", shopOrderEntity.getPayState());
        }
        if(shopOrderEntity.getPayType() != null){
            ops.set("payType", shopOrderEntity.getPayType());
        }
        if(shopOrderEntity.getRealPayMoney() != null){
            ops.set("realPayMoney", shopOrderEntity.getRealPayMoney());
        }
        if(shopOrderEntity.getUserFrom() != null){
            ops.set("userFrom", shopOrderEntity.getUserFrom());
        }
        datastore.update(shopOrderEntityQuery, ops);

        return true;
    }

    @Override
    public int updateReviewStateInOrder(String userId, String orderId, String skuCode, int reviewState, int orderState) {
        Query<ShopOrderEntity> shopOrderQuery_update = datastore
                .createQuery(ShopOrderEntity.class)
                .filter("userId", userId)
                .filter("shopOrderId", orderId)
                .filter("shoppingItems.skuCode", skuCode);
        //sku评价状态更改
        UpdateOperations<ShopOrderEntity> updateOperations = datastore
                .createUpdateOperations(ShopOrderEntity.class)
                .set("shoppingItems.$.reviewState", reviewState);
        datastore.update(shopOrderQuery_update, updateOperations);

        // spu评价状态更改
        ShopOrderEntity orderEntities = shopOrderQuery_update.get();
        if(orderEntities==null || StringUtils.isBlank(orderEntities.getId())){
            return 0;
        }
        List<ShoppingItem> shoppingItemList = orderEntities.getShoppingItems();
        if (shoppingItemList != null && shoppingItemList.size() > 1) {
            int i = 0;
            for (; i < orderEntities.getShoppingItems().size(); i++) {
                if (shoppingItemList.get(i).getReviewState()!=null &&
                        shoppingItemList.get(i).getReviewState()==0) {
                    return 1;
                }
            }
            //说明全都已经评价了
            if (i == shoppingItemList.size()) {
                UpdateOperations<ShopOrderEntity> updateSPUOperations = datastore
                        .createUpdateOperations(ShopOrderEntity.class)
                        .set("orderState", orderState);
                datastore.update(shopOrderQuery_update, updateSPUOperations);
            }
        } else if (shoppingItemList != null && shoppingItemList.size() == 1) {
            UpdateOperations<ShopOrderEntity> updateSPUOperations = datastore
                    .createUpdateOperations(ShopOrderEntity.class)
                    .set("orderState", orderState);
            datastore.update(shopOrderQuery_update, updateSPUOperations);
        }
        return 2;
    }

    @Override
    public void callBackReviewState(String userId, String shopOrderId, String skuCode,int orderState) {
        Query<ShopOrderEntity> shopOrderQuery_state_update = datastore
                .createQuery(ShopOrderEntity.class)
                .filter("userId", userId)
                .filter("shopOrderId", shopOrderId)
                .filter("shoppingItems.skuCode", skuCode);
        UpdateOperations<ShopOrderEntity> update = datastore.createUpdateOperations(ShopOrderEntity.class)
                .set("shoppingItems.$.reviewState", 0)
                .set("orderState", orderState);
        datastore.update(shopOrderQuery_state_update, update);
    }

    @Override
    public boolean deleteOrder(ShopOrderEntity shopOrderEntity) {
        if(shopOrderEntity==null || StringUtils.isBlank(shopOrderEntity.getShopOrderId())){
            return false;
        }

        Query<ShopOrderEntity> orderEntityQuery = datastore
                .createQuery(ShopOrderEntity.class)
                .filter("shopOrderId", shopOrderEntity.getShopOrderId());

        boolean flag = false;
        if(StringUtils.isNotBlank(shopOrderEntity.getUserId())){
            orderEntityQuery.filter("userId", shopOrderEntity.getUserId());
            flag = true;
        }
        if(StringUtils.isNotBlank(shopOrderEntity.getInterpreterId())){
            orderEntityQuery.filter("interpreterId", shopOrderEntity.getInterpreterId());
            flag = true;
        }

        if(!flag){
            return false;
        }

        UpdateOperations<ShopOrderEntity> ups = datastore.createUpdateOperations(ShopOrderEntity.class);

        long currentMillis = System.currentTimeMillis();
        ups.set("updatedAt", currentMillis);

        if(shopOrderEntity.getInterDeleteFlag() != null){
            ups.set("interDeleteFlag", shopOrderEntity.getInterDeleteFlag());
            ups.set("interDeleteTime", currentMillis);
        }
        if(shopOrderEntity.getUserDeleteFlag() != null){
            ups.set("userDeleteFlag", shopOrderEntity.getUserDeleteFlag());
            ups.set("userDeleteTime", currentMillis);
        }

        UpdateResults urs = datastore.update(orderEntityQuery,ups, false, WriteConcern.ACKNOWLEDGED);
        return urs.getUpdatedExisting();
    }

    @Override
    public List<ShopOrderEntity> getNotPayExpiredShopOrderList(String shopId, Integer orderType) {
        Query<ShopOrderEntity> orderEntityQuery = datastore
                .createQuery(ShopOrderEntity.class)
                .filter("payState", PayState.NOPAYMENT.value())
                .filter("payEndTime <", System.currentTimeMillis())
                .field("canceledTime").doesNotExist()
                .field("paidTime").doesNotExist()
                .filter("userDeleteFlag", ConstantUtil.NOT_DELETE_STATUS);
        if(StringUtils.isNotBlank(shopId)){
            orderEntityQuery.filter("shopId", shopId);
        }
        if(orderType != null){
            orderEntityQuery.filter("orderType", orderType);
        }

        return orderEntityQuery.asList();
    }

    @Override
    public List<ShopOrderEntity> getInterpreterAllOrder(String interpreterId, Integer orderState, Integer payState) {
        if(StringUtils.isBlank(interpreterId)){
            return new ArrayList<>();
        }
        Query<ShopOrderEntity> orderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("interpreterId", interpreterId)
                .filter("interDeleteFlag", ConstantUtil.NOT_DELETE_STATUS)
                .order("-createdAt");
        if(orderState != null){
            orderEntityQuery.filter("orderState", orderState.intValue());
        }
        if(payState != null){
            orderEntityQuery.filter("payState", payState.intValue());
        }
        return orderEntityQuery.asList();
    }

    @Override
    public List<ShopOrderEntity> getShopAllOrders(OrderQueryVo orderQueryVo, PagingVo pagingVo) {
        if(orderQueryVo==null || StringUtils.isBlank(orderQueryVo.getShopId())){
            return new ArrayList<>();
        }
        Query<ShopOrderEntity> orderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopId", orderQueryVo.getShopId())
                .order("-createdAt");
        if(orderQueryVo.getCreateTime() != null){
            orderEntityQuery.filter("createTime >= ", orderQueryVo.getCreateTime());
        }
        if(orderQueryVo.getEndOrderTime() != null){
            orderEntityQuery.filter("createTime <= ", orderQueryVo.getEndOrderTime());
        }
        if(orderQueryVo.getOrderState() != null){
            orderEntityQuery.filter("orderState", orderQueryVo.getOrderState());
        }
        if(orderQueryVo.getOrderType() != null){
            orderEntityQuery.filter("orderType", orderQueryVo.getOrderType());
        }
        if(orderQueryVo.getPayState() != null){
            orderEntityQuery.filter("payState", orderQueryVo.getPayState());
        }
        if(orderQueryVo.getPayType() != null){
            orderEntityQuery.filter("payType", orderQueryVo.getPayType());
        }
        if(StringUtils.isNotBlank(orderQueryVo.getShopOrderId())){
            orderEntityQuery.filter("shopOrderId", orderQueryVo.getShopOrderId());
        }
        if(CollectionUtils.isNotEmpty(orderQueryVo.getSpuCodeList())){
            orderEntityQuery.filter("shoppingItems.spuCode in", orderQueryVo.getSpuCodeList());
        }
        if(CollectionUtils.isNotEmpty(orderQueryVo.getSkuCodeList())){
            orderEntityQuery.filter("shoppingItems.skuCode in", orderQueryVo.getSkuCodeList());
        }
        if(CollectionUtils.isNotEmpty(orderQueryVo.getInterList())){
            orderEntityQuery.filter("interpreterId in", orderQueryVo.getInterList());
        }

        if(pagingVo != null){
            orderEntityQuery.offset(pagingVo.getPageOffset()).limit(pagingVo.getPs());
        }

        return orderEntityQuery.asList();
    }

    @Override
    public long getShopAllOrdersCount(OrderQueryVo orderQueryVo, PagingVo pagingVo) {
        if(orderQueryVo==null || StringUtils.isBlank(orderQueryVo.getShopId())){
            return 0L;
        }
        Query<ShopOrderEntity> orderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopId", orderQueryVo.getShopId())
                .order("-createdAt");
        if(orderQueryVo.getCreateTime() != null){
            orderEntityQuery.filter("createTime >= ", orderQueryVo.getCreateTime());
        }
        if(orderQueryVo.getEndOrderTime() != null){
            orderEntityQuery.filter("createTime <= ", orderQueryVo.getEndOrderTime());
        }
        if(orderQueryVo.getOrderState() != null){
            orderEntityQuery.filter("orderState", orderQueryVo.getOrderState());
        }
        if(orderQueryVo.getOrderType() != null){
            orderEntityQuery.filter("orderType", orderQueryVo.getOrderType());
        }
        if(orderQueryVo.getPayState() != null){
            orderEntityQuery.filter("payState", orderQueryVo.getPayState());
        }
        if(orderQueryVo.getPayType() != null){
            orderEntityQuery.filter("payType", orderQueryVo.getPayType());
        }
        if(StringUtils.isNotBlank(orderQueryVo.getShopOrderId())){
            orderEntityQuery.filter("shopOrderId", orderQueryVo.getShopOrderId());
        }
        if(CollectionUtils.isNotEmpty(orderQueryVo.getSpuCodeList())){
            orderEntityQuery.filter("shoppingItems.spuCode in", orderQueryVo.getSpuCodeList());
        }
        if(CollectionUtils.isNotEmpty(orderQueryVo.getSkuCodeList())){
            orderEntityQuery.filter("shoppingItems.skuCode in", orderQueryVo.getSkuCodeList());
        }
        if(CollectionUtils.isNotEmpty(orderQueryVo.getInterList())){
            orderEntityQuery.filter("interpreterId in", orderQueryVo.getInterList());
        }

        return orderEntityQuery.count();
    }

    @Override
    public List<ShopOrderEntity> getShopOrderList(String shopId, List<String> couponCodeList) {
        if(StringUtils.isBlank(shopId) || CollectionUtils.isEmpty(couponCodeList)){
            return new ArrayList<>();
        }
        Query<ShopOrderEntity> orderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopId", shopId)
                .filter("couponCode in", couponCodeList);

        return orderEntityQuery.asList();
    }

    @Override
    public List<ShopOrderEntity> getPaidNotUserFromOrders(Integer limit) {
        Query<ShopOrderEntity> orderEntityQuery = datastore.createQuery(ShopOrderEntity.class)
                .filter("payState", PayState.PAID.value())
                .field("userFrom").doesNotExist()
                .order("createdAt");
        if(limit != null){
            orderEntityQuery.limit(limit);
        }
        return orderEntityQuery.asList();
    }

    /**
     * 游客一览查询接口
     * @param orderQueryVo 查询Vo
     * @param pagingVo
     * @return
     */
    @Override
    public List<OrderTourPipe> getShopAllOrders4Tour(OrderTourPipeQueryVo orderQueryVo, PagingVo pagingVo) {
        List<OrderTourPipe> resultList = new ArrayList<>();
        Query<ShopOrderEntity> query = datastore.createQuery(ShopOrderEntity.class)
                .filter("shopId", orderQueryVo.getShopId());

        if(orderQueryVo.getPayState() != null){
            query.filter("payState =", orderQueryVo.getPayState());
        }
        if(StringUtils.isNotBlank(orderQueryVo.getUserId())){
            query.filter("userId =", orderQueryVo.getUserId());
        }
        if (orderQueryVo.getStartTime() != null){
            query.filter("createTime >=", orderQueryVo.getStartTime());
        }
        if (orderQueryVo.getEndTime() != null){
            query.filter("createTime <=", orderQueryVo.getEndTime());
        }

        if(StringUtils.isNotBlank(orderQueryVo.getUserFrom())){
            query.field("userFrom").containsIgnoreCase(orderQueryVo.getUserFrom());
        }

        AggregationPipeline pipeline = datastore.createAggregation(ShopOrderEntity.class)
                .match(query)
                .group(id(grouping("userId")),   //以 matchTxt 分组
                        grouping("userId",first("userId")),
                        grouping("shopId",first("shopId")),
                        grouping("userFrom",first("userFrom")),
                        grouping("totalAmount",new Accumulator("$sum", "realPayMoney")),
                        grouping("orderCount",new Accumulator("$sum", 1))
                );

        Query<ShopOrderEntity> pipelineQuery = datastore.createQuery(ShopOrderEntity.class);
        if(orderQueryVo.getConsumeMinMoney() != null){
            pipelineQuery.filter("totalAmount >", orderQueryVo.getConsumeMinMoney());
        }
        if(orderQueryVo.getConsumeMaxMoney() != null){
            pipelineQuery.filter("totalAmount <", orderQueryVo.getConsumeMaxMoney());
        }
        if(orderQueryVo.getOrderCount() != null){
            //orderCount 不在ShopOrderEntity中,disable验证
            pipelineQuery.disableValidation().filter("orderCount >=", orderQueryVo.getOrderCount());
        }

        pipeline.match(pipelineQuery);
        if(pagingVo != null){
            pipeline.skip(pagingVo.getPageOffset()).limit(pagingVo.getPs());
        }
        pipeline.sort(Sort.descending("totalAmount"));

        Iterator<OrderTourPipe> iterator = pipeline.aggregate(OrderTourPipe.class);

        while (iterator.hasNext()) {
            resultList.add(iterator.next());
        }
        return resultList;
    }

    /**
     * 游客一览查询接口, 总条数
     * @param orderQueryVo 查询Vo
     * @return
     */
    @Override
    public long getShopAllOrders4TourCount(OrderTourPipeQueryVo orderQueryVo) {
        long totalCount = 0L;
        Query<ShopOrderEntity> query = datastore.createQuery(ShopOrderEntity.class)
                .filter("payState =", PayState.PAID.value())
                .filter("shopId", orderQueryVo.getShopId());
        if(StringUtils.isNotBlank(orderQueryVo.getUserFrom())){
            query.field("userFrom").containsIgnoreCase(orderQueryVo.getUserFrom());
        }
        if(StringUtils.isNotBlank(orderQueryVo.getUserId())){
            query.filter("userId =", orderQueryVo.getUserId());
        }
        AggregationPipeline pipeline = datastore.createAggregation(ShopOrderEntity.class)
                .match(query)
                .group(id(grouping("userId")),   //以 matchTxt 分组
                        grouping("userId",first("userId")),
                        grouping("shopId",first("shopId")),
                        grouping("userFrom",first("userFrom")),
                        grouping("totalAmount",new Accumulator("$sum", "realPayMoney")),
                        grouping("orderCount",new Accumulator("$sum", 1))
                );

        Query<ShopOrderEntity> pipelineQuery = datastore.createQuery(ShopOrderEntity.class);
        if(orderQueryVo.getConsumeMinMoney() != null){
            pipelineQuery.filter("totalAmount >", orderQueryVo.getConsumeMinMoney());
        }
        if(orderQueryVo.getConsumeMaxMoney() != null){
            pipelineQuery.filter("totalAmount <", orderQueryVo.getConsumeMaxMoney());
        }
        if(orderQueryVo.getOrderCount() != null){
            //orderCount 不在ShopOrderEntity中,disable验证
            pipelineQuery.disableValidation().filter("orderCount >=", orderQueryVo.getOrderCount());
        }

        pipeline.match(pipelineQuery);

        Iterator<OrderTourPipe> iterator = pipeline.aggregate(OrderTourPipe.class);

        while (iterator.hasNext()) {
            iterator.next();
            totalCount++;
        }
        return totalCount;
    }
}
